<?php
namespace Model;

require_once 'Model.php';
require_once 'AnnonceAttribut.php';

use Model\AnnonceAttribut;
use Classes\Field;
use Classes\Upload;

use Model\Model;

class Attribut extends Model {
    private $table = 'attribut';
    public $id_attribut;
    public $libelle;
    public $alias;
    public $type;
    public $predefined_option;
    public $predefined_value;
    public $default_value;
    public $affected_value;
    public $css_class;
    public $position;
    public $active;
    public $col_title;
    public $col;
    public $search;
    public $required;
    public $value;
    public $html;
    
    public function __construct($data = array()) {
        parent::__construct();
        $this->id_attribut = isset($data['id_attribut'])?$data['id_attribut']:null;
        $this->libelle = isset($data['libelle'])?$data['libelle']:null;
        $this->alias = isset($data['alias'])?$data['alias']:null;
        $this->type = isset($data['type'])?$data['type']:null;
        $this->predefined_option = isset($data['predefined_option'])?$data['predefined_option']:null;
        $this->predefined_value = isset($data['predefined_value'])?$data['predefined_value']:null;
        $this->default_value = isset($data['default_value'])?$data['default_value']:null;
        $this->affected_value = isset($data['affected_value'])?$data['affected_value']:null;
        $this->css_class = isset($data['css_class'])?$data['css_class']:null;
        $this->position = isset($data['position'])?$data['position']:null;
        $this->active = isset($data['active'])?$data['active']:null;
        $this->col_title = isset($data['col_title'])?$data['col_title']:null;
        $this->col = isset($data['col'])?$data['col']:null;
        $this->search = isset($data['search'])?$data['search']:null;
        $this->required = isset($data['required'])?$data['required']:null;
        $this->value = isset($data['value'])?$data['value']:null;
        $this->html = isset($data['html'])?$data['html']:null;
    }
    
    /**
     * Retourne le nombre total d'enregistrement
     * @param int $active : NULL(aucun filtre), 0(filtre sur 0) ou 1(filtre sur 1)
     * @return objet $result
     */
    public function getTotalCount($active=null) {
        $query = 'SELECT COUNT(*) AS total'
                . ' FROM '.$this->table;
        
        // Si le champ active est spécifié
        $where = '';
        if(is_numeric($active)) {
            $where = ' WHERE active = '.$active;
        }   
        $query .= $where;
        
        $select = $this->db->prepare($query);
        $select->setFetchMode(\PDO::FETCH_OBJ);
        try {
            $select->execute();
            $result = $select->fetch();
            return $result;
        } catch (Exception $ex) {
            echo 'Erreur de requète : ', $ex->getMessage();
        }
    }
    
    /**
     * Retourne une liste des attributs
     * @param int $active : NULL(aucun filtre), 0(filtre sur 0) ou 1(filtre sur 1)
     * @param string $sort : Nom du champ sur lequel s'effectue le tri
     * @param string $sortdir : Sens du tri
     * @param int $limit_start : Position à partir duquel on récupère les enregistrements
     * @param int $items_per_page : Nombre d'enregistrement à afficher par page
     * @param int $id_annonce : Id de l'annonce désiré
     * @param boolean $html : Spécifie si l'on veut avoir le rendu html de tous les attributs
     * @return array $result
     */
    public function fetchAll($active=null, $sort='position', $sortdir='ASC', $limit_start=null, $items_per_page=null, $id_annonce=null, $html=false) {
        $result = array();        
        $query = 'SELECT *'
                . ' FROM '.$this->table;
        
        // Si le champ active est spécifié
        $where = '';
        if(is_numeric($active)) {
            $where = ' WHERE active = '.$active;
        }   
        $query .= $where;
        
        // Si un tri sur un champ est demandé
        if($sort && $sortdir) {
            $orderby = ' ORDER BY '.$sort.' '.$sortdir;
        } elseif($sort && !$sortdir) {
            $orderby = ' ORDER BY '.$sort;
        } else {
            $orderby = ' ORDER BY position ASC';
        }
        $query .= $orderby;
        
        // Si une pagination sur les résultats est demandée
        if($limit_start && $items_per_page) { 
            $limit = ' LIMIT '.$limit_start.', '.$items_per_page; 
            
        } elseif(!$limit_start && $items_per_page) { 
            $limit = ' LIMIT '.$items_per_page;             
        } else { 
            $limit = '';            
        }
        $query .= $limit;
        
        $select = $this->db->prepare($query);
        $select->setFetchMode(\PDO::FETCH_OBJ);
        //echo $select->queryString;
        try {            
            $select->execute();
            $attributs = $select->fetchAll();
            foreach($attributs as $attribut) {                
                $result[] = $this->getAttribut($attribut->id_attribut, $id_annonce, $html);
            }
            // Retourne la liste des attribut
            return $result;
        } catch (Exception $ex) {
            echo 'Erreur de requète : ', $ex->getMessage();
        }
    }
    
    /**
     * Retourne la liste des attributs qui peuvent être affichés en tant que colonne
     * @return array $result
     */
    public function fetchAllCol() {
        $query = 'SELECT * FROM '.$this->table
                . ' WHERE active = 1'
                . ' AND col = 1'
                . ' ORDER BY position ASC';                
        $select = $this->db->prepare($query);
        $select->setFetchMode(\PDO::FETCH_OBJ);
        try {            
            $select->execute();
            $result = $select->fetchAll();
            return $result;
        } catch (Exception $ex) {
            echo 'Erreur de requète : ', $ex->getMessage();
        }
    }
    
    /**
     * Retourne la liste des attributs qui peuvent être recherchés
     * @return array $result
     */
    public function getAllSearchIds() {
        $attributIds = array();
        $query = 'SELECT id_attribut FROM '.$this->table
                . ' WHERE active = 1'
                . ' AND search = 1';
        $select = $this->db->prepare($query);
        $select->setFetchMode(\PDO::FETCH_OBJ);
        try {
            $select->execute();
            $ids = $select->fetchAll();
            foreach($ids as $id) {
                $attributIds[] = $id->id_attribut;
            }
            $result = implode(',', $attributIds);
            return $result;
        } catch (Exception $ex) {
            echo 'Erreur de requète : ', $ex->getMessage();
        }
    }
    
    /**
     * Retourne un attribut
     * @param int $id_attribut : Id de l'attribut à récupérer
     * @param int $id_annonce : Id de l'annonce désiré
     * @param boolean $html : Spécifie si l'on veut avoir le rendu html de l'attribut
     * @return object $result
     */
    public function getAttribut($id_attribut, $id_annonce=null, $html=false) {
        $data = array();
        $id_attribut = (int) $id_attribut;
        $field = new Field();
        $annonceAttributObject = new AnnonceAttribut();
        $query = 'SELECT *'
                . ' FROM '.$this->table
                . ' WHERE id_attribut = '.$id_attribut;
        $select = $this->db->prepare($query);
        $select->setFetchMode(\PDO::FETCH_OBJ);
        try {            
            $select->execute();
            $result = $select->fetch();
            
            $data['id_attribut'] = isset($result->id_attribut)?$result->id_attribut:null;
            $data['libelle'] = isset($result->libelle)?$result->libelle:null;
            $data['alias'] = isset($result->alias)?$result->alias:null;
            $data['type'] = isset($result->type)?$result->type:null;
            $data['predefined_option'] = isset($result->predefined_option)?$result->predefined_option:null;
            $data['predefined_value'] = isset($result->predefined_value)?$result->predefined_value:null;
            $data['default_value'] = isset($result->default_value)?$result->default_value:null;
            $data['affected_value'] = isset($result->affected_value)?$result->affected_value:null;
            $data['css_class'] = isset($result->css_class)?$result->css_class:null;
            $data['position'] = isset($result->position)?$result->position:null;
            $data['active'] = isset($result->active)?$result->active:null;            
            $data['col_title'] = isset($result->col_title)?$result->col_title:null;
            $data['col'] = isset($result->col)?$result->col:null;
            $data['search'] = isset($result->search)?$result->search:null;
            $data['required'] = isset($result->required)?$result->required:null;
            
            $value = $annonceAttributObject->getAnnonceAttribut($id_annonce, $data['id_attribut']);
            $data['value'] = ($value)?$value->value:''; 
            $data['html'] = null;
            
            // Si le rendu html est demandé
            if($html) { 
                // Retourne la valeur par défaut si le champ est vide (TEXT,HIDDEN,DATE,DATEHIDDEN)
                $value = $data['value'];
                if($data['default_value'] && $data['value']=='' && ($data['type']==Field::TEXT || $data['type']==Field::HIDDEN || $data['type']==Field::DATE || $data['type']==Field::DATEHIDDEN)) {
                    $value = $field->$data['default_value']();
                }
                
                // Retourne la valeur affectée au champ (TEXT,HIDDEN,DATE,DATEHIDDEN)
                if($data['affected_value'] && ($data['type']==Field::TEXT || $data['type']==Field::HIDDEN || $data['type']==Field::DATE || $data['type']==Field::DATEHIDDEN)) {
                    $value = $field->$data['affected_value']();
                }
                
                // Retourne le rendu html
                $data['html'] = $field->getHTML($data['type'], $data['alias'], $data['css_class'], $data['predefined_option'], $data['predefined_value'], $value, $data['required']);
            }
            
            // Retourne l'option correspondante à la valeur (SELECT, RADIO)
            if($data['predefined_option'] && ($data['type']==Field::SELECT || $data['type']==Field::RADIO)) {
                $pOptions = explode(',', $data['predefined_option']);
                $pValues = explode(',', $data['predefined_value']);
                foreach($pValues as $idx => $pValue) {
                    if($data['value'] == $pValue) {
                        $data['value'] = $pOptions[$idx];
                    }
                }    
            }
            
            // Retourne l'option correspondante à la valeur (CHECKBOX)
            if($data['predefined_option'] && $data['type']==Field::CHECKBOX) {
                $valueText = '';
                $pOptions = explode(',', $data['predefined_option']);
                $pValues = explode(',', $data['predefined_value']);
                foreach($pValues as $idx => $pValue) {
                    $values = explode(',', $data['value']);
                    foreach($values as $value) {
                        if($value == $pValue) {
                            $valueText .= ($valueText)?','.$pOptions[$idx]:$pOptions[$idx];
                        }
                    }
                } 
                $data['value'] = $valueText;
            }
            
            // Retourne une date formatée
            if($data['value'] && ($data['type']==Field::DATE || $data['type']==Field::DATEHIDDEN)) {
                $date = new \DateTime($data['value']);
                $data['value'] = $date->format('d-M-Y');
            }
            
            // Retourne l'objet
            return new Attribut($data);
        } catch (Exception $ex) {
            echo 'Erreur de requète : ', $ex->getMessage();
        }        
    }
    
    /**
     * Retourne un attribut par son alias
     * @param int $alias : Alias de l'attribut à récupérer
     * @param int $id_annonce : Id de l'annonce désiré
     * @return object $result
     */
    public function getAttributByAlias($alias, $id_annonce=null) {
        $data = array();
        $annonceAttributObject = new AnnonceAttribut();
        $query = 'SELECT *'
                . ' FROM '.$this->table
                . ' WHERE alias = "'.$alias.'"';
        $select = $this->db->prepare($query);
        $select->setFetchMode(\PDO::FETCH_OBJ);
        try {            
            $select->execute();
            $result = $select->fetch();
            
            $data['id_attribut'] = isset($result->id_attribut)?$result->id_attribut:null;
            $data['libelle'] = isset($result->libelle)?$result->libelle:null;
            $data['alias'] = isset($result->alias)?$result->alias:null;
            $data['type'] = isset($result->type)?$result->type:null;
            $data['predefined_option'] = isset($result->predefined_option)?$result->predefined_option:null;
            $data['predefined_value'] = isset($result->predefined_value)?$result->predefined_value:null;
            $data['default_value'] = isset($result->default_value)?$result->default_value:null;
            $data['affected_value'] = isset($result->affected_value)?$result->affected_value:null;
            $data['css_class'] = isset($result->css_class)?$result->css_class:null;
            $data['position'] = isset($result->position)?$result->position:null;
            $data['active'] = isset($result->active)?$result->active:null;
            $data['col_title'] = isset($result->col_title)?$result->col_title:null;
            $data['col'] = isset($result->col)?$result->col:null;
            $data['search'] = isset($result->search)?$result->search:null;
            $data['required'] = isset($result->required)?$result->required:null;
            $data['value'] = null;
            $data['html'] = null;
            
            // Retourne l'objet
            return new Attribut($data);
        } catch (Exception $ex) {
            echo 'Erreur de requète : ', $ex->getMessage();
        }        
    }
            
    /**
     * Enregistre une insertion ou une modification d'un attribut
     * @param array $data : Données à enregistrer dans la table
     */
    public function saveAttribut(Array $data) {
        $id_attribut = (int) $data['id_attribut'];
        if($id_attribut == 0) {
            $query = 'INSERT INTO '.$this->table.' VALUES ('
                    . ' :id_attribut,'
                    . ' :libelle,'
                    . ' :alias,'
                    . ' :type,'
                    . ' :predefined_option,'
                    . ' :predefined_value,'
                    . ' :default_value,'
                    . ' :affected_value,'
                    . ' :css_class,'
                    . ' :position,'
                    . ' :active,'
                    . ' :col_title,'
                    . ' :col,'
                    . ' :search,'
                    . ' :required)';
            $insert = $this->db->prepare($query);            
            try {
                // Insert l'attribut
                $insert->execute($data);
                return true;
            } catch (Exception $ex) {
                echo 'Erreur de requète : ', $ex->getMessage();
            }
        } else {
            $query = 'UPDATE '.$this->table.' SET'
                    . ' id_attribut = :id_attribut,'
                    . ' libelle = :libelle,'
                    . ' alias = :alias,'
                    . ' type = :type,'
                    . ' predefined_option = :predefined_option,'
                    . ' predefined_value = :predefined_value,'
                    . ' default_value = :default_value,'
                    . ' affected_value = :affected_value,'
                    . ' css_class = :css_class,'
                    . ' position = :position,'
                    . ' active = :active,'
                    . ' col_title = :col_title,'
                    . ' col = :col,'
                    . ' search = :search,'
                    . ' required = :required'
                    . ' WHERE id_attribut = '.$id_attribut;
            $update = $this->db->prepare($query); 
            try {
                // Modifie l'attribut
                $update->execute($data);
                return true;
            } catch (Exception $ex) {
                echo 'Erreur de requète : ', $ex->getMessage();
            }
        }
    }
    
    /**
     * Supprime un attribut
     * @param int $id_attribut : Id de l'attribut à supprimer
     */
    public function deleteAttribut($id_attribut) {
        $id_attribut = (int) $id_attribut;
        $upload = new Upload();
        $annonceAttributObject = new AnnonceAttribut();
        $query = 'DELETE'
                . ' FROM '.$this->table
                . ' WHERE id_attribut = '.$id_attribut;        
        try {
            // Supprime les fichiers ou les images relatifs à l'attribut
            $attribut = $this->getAttribut($id_attribut);
            if($attribut->type == Field::IMAGE || $attribut->type == Field::FILE) {
                $values = $annonceAttributObject->getAttributValues($id_attribut);
                if($values) {
                    foreach($values as $value) {
                        $upload->deleteFile($value->value);
                    }
                }
            }
             
            // Supprime les valeurs relatifs à l'attribut
            $annonceAttributObject->deleteAnnonceAttribut($id_attribut, 'attribut');
            
            // Supprime l'attribut
            $this->db->exec($query);
            return true;
        } catch (Exception $ex) {
            echo 'Erreur de requète : ', $ex->getMessage();
        }
    }
}

